/*
 * amplitude_scrambling.h
 *
 *  Created on: Apr 12, 2011
 *      Author: Paul Woelfel
 */

#ifndef ADV_AMPLITUDE_SCRAMBLING_H_
#define ADV_AMPLITUDE_SCRAMBLING_H_

#include <fftw3.h>
#include "crypto_engine.h"
#include "buffer.h"

/**
 * The Advanced Amplitude Scrambling class generates a FFT signal from the cipher stream and adds this values to signal.
 */
class CAdvAmplitudeScrambling: public CCryptoEngine {
public:
	CAdvAmplitudeScrambling(NAudioFormats::SStreamInfo ioStreamInfo);

	virtual ~CAdvAmplitudeScrambling();

	/**
	 * abstract method encrypt
	 * encrypt pCount bytes from data and write them back to data
	 * if not enough data is available for encryption, zeros should
	 * be written to the data buffer
	 * @param data double array with amplitude values from -1.0 to 1.0
	 * @param pCount count of audio samples to work with
	 * @return 0 for success, >0 for success and discard of samples for next
	 *         call, <0 for an error
	 */
	virtual int encrypt(double *pData, unsigned int pCount);

	/**
	 * abstract method decrypt
	 * decrypt pCount bytes from data and write them back to data
	 * if not enough data is available for decryption, zeros should
	 * be written to the data buffer
	 * @param data double array with amplitude values from -1.0 to 1.0
	 * @param pCount count of audio samples to work with
	 * @return 0 for success, >0 for success and discard of samples for next
	 *         call, <0 for an error
	 */
	virtual int decrypt(double *pData, unsigned int pCount);

protected:
	/**
	 * called by the protocol engine upon settings change
	 * (e.g. change of embedding parameters)
	 * calls setProperties and initCrypto
	 * if this method gets overwritten, the subclass should call
	 * setProperties and initCrypto
	 */
	virtual int changeSettings();

	/**
	 * encrypt or decrypt some bytes
	 * Encryption and decryption is the same algorithm, just plus or minus. One method does it all
	 */
	int dencrypt(double * pData, unsigned int pCount, bool encrypt);

	/**
	 * create a new cipher signal
	 * @return 	0 for success
	 * 			!=0 for failure
	 */
	int generateKeySignal();

	void normalizeKeySignal();

	/**
	 * for how many double values should the signal be generated
	 */
	unsigned int mKeySignalLength;

	/**
	 * how often should the signal be repeated
	 */
	double mKeySignalRepetition;

	/**
	 * how many values have been en/decrypted since last cipher signal generation
	 */
	unsigned int mKeySignalValuesLeft;

	/**
	 * at which byte are we at the moment
	 */
	unsigned int mKeySignalPos;

	/**
	 * how many fft waves should be used
	 */
	unsigned int mKeySignalFourierWaveCount;

	/**
	 * mirror ifft frequencies
	 */
	bool mKeySignalMirrorFrequencies;

	/**
	 * iFFT Scaling
	 *
	 */
	double mKeySignalScale;

	/**
	 * factors for scaling key and data signal
	 */
	double mKeySignalFactor,mDataSignalFactor;



	int mTotalSampleCount;

	/*
	 * use only speech frequencies for the generated signal
	 */
	unsigned int mKeySignalSpeechOnly, mKeySignalSpeechFreqStart, mKeySignalSpeechFreqStop;

	/**
	 * the actual fft wave data
	 */
	fftw_complex *mFftData;


private:
	static const std::string sIniSectionName;


};

#endif /* ADV_AMPLITUDE_SCRAMBLING_H_ */
